<template>
  <div class="flv-player">
    <div class="flv-input">
      <el-select v-model="type" style="width: 100px">
        <el-option v-for="t in types" :value="t" :key="t" :label="t" />
      </el-select>
      <el-select v-model="url" filterable allow-create style="width: 100%">
        <el-option v-for="t in examples" :value="t" :key="t" :label="t" />
      </el-select>
      <el-button size="default" type="primary" @click="play">播放</el-button>
      <el-button size="default" @click="close">关闭</el-button>
    </div>
    <video class="player-video" ref="player" muted autoplay></video>
  </div>
</template>
<script>
import FlvExtend from '@/utils/flvExtend.js'
import flvjs from 'flv.js'
import Hls from 'hls.js'
export default {
  data() {
    return {
      types: ['flv', 'rtsp', 'hls'],
      type: 'flv',
      url: '',
      id: `${Date.now()}`,
      examples: [
        'rtsp://admin:tmq123456789@61.48.133.124:10554/Streaming/Channels/101',
        'rtsp://wowzaec2demo.streamlock.net/vod/mp4:BigBuckBunny_115k.mp4',
        'rtmp://ns8.indexforce.com/home/mystream',
        'rtmp://mobliestream.c3tv.com:554/live/goodtv.sdp',
        'http://192.168.31.97:8080/live/test.live.flv',
        'https://sf1-hscdn-tos.pstatp.com/obj/media-fe/xgplayer_doc_video/flv/xgplayer-demo-360p.flv',
        'https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8',
        'http://playertest.longtailvideo.com/adaptive/bipbop/gear4/prog_index.m3u8'
      ],
      rtsp: 'rtsp://admin:tmq123456789@192.168.31.10:554/Streaming/Channels/101',
      player: null,
      flvInstance: null
    }
  },
  beforeUnmount() {
    this.flvInstance.destroy()
  },
  methods: {
    play() {
      if (!this.url) {
        return
      }
      if (this.flvInstance) {
        this.flvInstance.destroy()
      }
      if (this.hlsInstance) {
        this.hlsInstance.destroy()
      }
      if (this.type === 'flv') {
        this.playFlv(this.url, true)
      } else if (this.type === 'rtsp') {
        const env = import.meta.env.VITE_USER_NODE_ENV
        const wsUrl =
          env === 'development'
            ? `ws://localhost:8888/rtsp/${this.id}/?url=${encodeURIComponent(
                decodeURIComponent(this.url)
              )}`
            : `${location.origin.replace('http', 'ws')}/rtsp/${this.id}/?url=${encodeURIComponent(
                decodeURIComponent(this.url)
              )}`
        this.playRtsp(wsUrl)
      } else if (this.type === 'hls') {
        this.playHls(this.url)
      }
    },
    playFlv(url, isLive = false) {
      if (isLive) {
        this.playRtsp(url)
      } else {
        let flvPlayer = flvjs.createPlayer({
          type: 'flv',
          url: url
        })
        flvPlayer.attachMediaElement(this.$refs.player)
        flvPlayer.load()
        flvPlayer.play()
        this.flvInstance = flvPlayer
      }
    },
    playRtsp(url) {
      // 配置需要的功能
      const flv = new FlvExtend({
        element: this.$refs.player, // *必传
        frameTracking: true, // 开启追帧设置
        updateOnStart: true, // 点击播放后更新视频
        updateOnFocus: true, // 获得焦点后更新视频
        reconnect: true, // 开启断流重连
        reconnectInterval: 0 // 断流重连间隔
      })
      this.flvInstance = flv

      // 调用 init 方法初始化视频
      // init 方法的参数与 flvjs.createPlayer 相同，并返回 flvjs.player 实例
      this.player = flv.init(
        {
          type: 'flv',
          url,
          isLive: true
        },
        {
          enableStashBuffer: false, // 如果您需要实时（最小延迟）来进行实时流播放，则设置为false
          autoCleanupSourceBuffer: true, // 对SourceBuffer进行自动清理
          stashInitialSize: 128 // 减少首帧显示等待时长
        }
      )
      // 直接调用play即可播放
      this.player.play()
    },
    playHls(url) {
      console.log(url)
      if (Hls.isSupported()) {
        var hls = new Hls()
        hls.loadSource(url)
        hls.attachMedia(this.$refs.player)

        this.hlsInstance = hls

        hls.on(Hls.Events.ERROR, function (event, data) {
          if (data.fatal) {
            switch (data.type) {
              case Hls.ErrorTypes.NETWORK_ERROR: // try to recover network error
                console.log('fatal network error encountered, try to recover')
                hls.startLoad()
                break
              case Hls.ErrorTypes.MEDIA_ERROR:
                console.log('fatal media error encountered, try to recover')
                hls.recoverMediaError()
                break
              default: // cannot recover
                hls.destroy()
                break
            }
          }
        })
      }
    },
    close() {
      if (this.flvInstance) {
        this.flvInstance.destroy()
      }
      if (this.hlsInstance) {
        this.hlsInstance.destroy()
      }
    }
  }
}
</script>
<style lang="less" scoped>
.flv-player {
  width: 100%;
  height: 100%;

  .flv-input {
    display: flex;
    align-items: center;
  }

  .player-video {
    width: 100%;
    max-height: 100%;
  }
}
</style>
